/**
 * This file is part of AppStoreBot.
 *
 *  AppStoreBot is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  AppStoreBot is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with AppStoreBot.  If not, see <http://www.gnu.org/licenses/>.
 *
 */
package lu.pragmaconsult.appstorebot.itunes;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.jxpath.JXPathContext;
import org.cyberneko.html.parsers.DOMParser;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

/**
 * TODO: Type comment
 * 
 * @author Wilfried Vandenberghe (wilfried.vandenberghe at pragmaconsult.lu)
 */
class HtmlParser {

	private static final String NOTIFICATION = "//DIV[@class = 'notification']";
	private static final String DAY_OPTION_VALUE = "//SELECT[contains(@id,'datePickerSourceSelectElementSales')]/OPTION/@value";
	private static final String WEEK_OPTION_VALUE = "//SELECT[contains(@id,'weekPickerSourceSelectElement')]/OPTION/@value";
	private static final String SCRIPT_ID = "//SCRIPT[contains(@id,'theForm:j_id_jsp_') and contains(@id,'_6')]/@id";
	private static final String INPUT_STATE = "//INPUT[@id='javax.faces.ViewState']/@value";
	private static final String FORM_ACTION = "//FORM/@action";
	
	private Document doc;
	private JXPathContext xpathContext;

	/**
	 * 
	 * @param stream
	 * @throws Exception
	 */
	public HtmlParser(InputStream stream) throws Exception {
		InputSource source = new InputSource(stream);
		DOMParser parser = new DOMParser();

		try {
			parser.parse(source);
		} catch (SAXException e) {
			throw new IllegalStateException("HTML cannot be parsed", e);
		}
		doc = parser.getDocument();
		xpathContext = JXPathContext.newContext(parser.getDocument());
	}

	/**
	 * 
	 * @param pattern
	 * @param constant
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	<T> T evaluate(String pattern) {
		T result = (T) xpathContext.getValue(pattern);
		if (result == null) {
			throw new IllegalStateException("Expression " + pattern
					+ " has been evaluated but not result are found.");
		}

		return result;
	}

	/**
	 * 
	 * @return
	 */
	Document getDocument() {
		return doc;
	}

	String getFormAction() {
		return evaluate(FORM_ACTION);
	}
	
	String getState() {
		return evaluate(INPUT_STATE);
	}
	
	String getScriptId() {
		return evaluate(SCRIPT_ID);
	}
	
	List<String> getDayOptionValues(){
		return getOptionValues(DAY_OPTION_VALUE);
	}
	
	List<String> getWeekOptionValues(){
		return getOptionValues(WEEK_OPTION_VALUE);
	}
	
	@SuppressWarnings("unchecked")
	private final List<String> getOptionValues(final String expression){
		Iterator iterator = xpathContext.iterate(expression);
		List<String> result = new ArrayList<String>();
		while(iterator.hasNext()) {
			result.add((String) iterator.next());
		}
		
		return result;
	}
	
	String getNotifications() {
		return evaluate(NOTIFICATION);
	}
	
	String getVendorPageId() {
		return evaluate("//SCRIPT[contains(@id,'defaultVendorPage')]/@id");
	}
}
